import random, string
import csv


def sui_number(a, b):
    return random.randint(a, b)


def sui_letters(n: int, upper=False, lower=False, unique=False):
    """
    n: 需要几个字母
    upper/lower: 二选一 True 则只给大写/小写；都 False 则大小写混合
    unique: True 时保证不重复（n 不能 > 52）
    """
    pool = string.ascii_uppercase if upper else \
        string.ascii_lowercase if lower else \
            string.ascii_letters

    if unique:
        if n > len(pool):
            raise ValueError('n 太大，字母池不够')
        return ''.join(random.sample(pool, n))
    return ''.join(random.choices(pool, k=n))


def suiji_lib():
    books = []
    for i in range(100):
        books.append(
            Book(sui_letters(10), sui_number(20, 70), sui_number(15, 30), i, sui_letters(1), sui_number(100, 300)))
    print("-" * 20, "随机图书馆生成", "-" * 20)
    write_books_csv(books)


class Book:
    def __init__(self, title, prize, cben, number, sub, shuliang, ):
        self.title = title
        self.prize = prize
        self.cben = cben
        self.number = number
        self.sub = sub
        self.shuliang = shuliang

    def show(self):
        """格式化显示单本书籍信息"""
        print(
            f"书名：{self.title} | 价格：{self.prize} | 成本：{self.cben} | 编号：{self.number} | 分类：{self.sub} | 库存量：{self.shuliang}")

    def show_detailed(self):
        """显示书籍详细信息，每项单独一行"""
        print(f"书名：{self.title}")
        print(f"价格：{self.prize}")
        print(f"成本：{self.cben}")
        print(f"编号：{self.number}")
        print(f"分类：{self.sub}")
        print(f"库存量：{self.shuliang}\n")


def read_books_csv(filename='library.csv'):
    books = []
    try:
        with open(filename, newline='', encoding='utf-8') as f:
            reader = csv.reader(f)
            header = next(reader)  # 获取表头
            print(f"表头信息: {header}")  # 调试用，可删除

            for row_num, row in enumerate(reader, 2):  # 从第2行开始计数
                if len(row) < 6:
                    print(f"警告: 行 {row_num} 数据不完整，跳过")
                    continue
                try:
                    # 确保列索引正确映射
                    title = row[0]
                    prize = int(row[1])
                    cben = int(row[2])
                    number = int(row[3])  # 编号列
                    sub = row[4]
                    shuliang = int(row[5])  # 库存列

                    books.append(Book(title, prize, cben, number, sub, shuliang))
                except ValueError as e:
                    print(f"行 {row_num} 数据转换错误: {e}，跳过")
    except FileNotFoundError:
        print(f"文件 {filename} 不存在，将生成新的随机图书馆数据。")
        suiji_lib()
        # 生成后再次读取
        with open(filename, newline='', encoding='utf-8') as f:
            next(f)  # 跳过表头
            for row in csv.reader(f):
                books.append(Book(row[0], int(row[1]), int(row[2]), int(row[3]), row[4], int(row[5])))
    return books


def write_books_csv(books, filename='library.csv'):
    header = ['title', 'prize', 'cben', 'number', 'sub', 'shuliang']
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(header)
        for b in books:
            writer.writerow([b.title, b.prize, b.cben, b.number, b.sub, b.shuliang])


# 用户类
class User:
    def __init__(self, username, password, is_admin=False, borrow_history=None, purchase_history=None):
        self.username = username
        self.password = password
        self.is_admin = is_admin  # 是否为管理员，管理员可进行书籍管理等操作
        # 初始化借书历史和购买历史，若为 None 则设为空列表
        self.borrow_history = borrow_history if borrow_history is not None else []
        self.purchase_history = purchase_history if purchase_history is not None else []


# 从用户数据 CSV 文件读取用户信息
def read_users_csv(filename='users.csv'):
    users = []
    try:
        with open(filename, newline='', encoding='utf-8') as f:
            next(f)  # 跳过表头
            for row in csv.reader(f):
                # 解析借书历史和购买历史，按逗号分割成列表
                borrow_history = row[3].split(',') if row[3] else []
                purchase_history = row[4].split(',') if row[4] else []
                users.append(User(row[0], row[1], row[2] == 'True', borrow_history, purchase_history))
    except FileNotFoundError:
        print(f"文件 {filename} 不存在，将使用初始模拟用户数据。")
        # 模拟用户数据，前三个为管理员
        users = [
            User("user1", "123456", True),
            User("user2", "123456", True),
            User("user3", "123456", True),
            User("user4", "123456"),
            User("user5", "123456")
        ]
        # 将初始用户数据写入 CSV 文件
        write_users_csv(users)
    return users


# 向用户数据 CSV 文件写入用户信息
def write_users_csv(users, filename='users.csv'):
    header = ['username', 'password', 'is_admin', 'borrow_history', 'purchase_history']
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(header)
        for user in users:
            # 将借书历史和购买历史用逗号连接成字符串
            borrow_str = ','.join(user.borrow_history)
            purchase_str = ','.join(user.purchase_history)
            writer.writerow([user.username, user.password, user.is_admin, borrow_str, purchase_str])


# 用户注册
def user_register(users):
    username = input("请输入要注册的用户名：")
    # 检查用户名是否已存在
    for user in users:
        if user.username == username:
            print("该用户名已存在，请重新注册。")
            return users
    password = input("请输入密码：")
    # 验证密码长度
    if len(password) < 6:
        print("密码长度不能少于6位，请重新注册。")
        return users
    # 新注册用户默认为非管理员
    users.append(User(username, password))
    # 将新用户信息写入 CSV 文件
    write_users_csv(users)
    print("注册成功！")
    return users


# 用户登录
def user_login(users):
    username = input("请输入用户名：")
    password = input("请输入密码：")
    for user in users:
        if user.username == username and user.password == password:
            print("登录成功！")
            return user
    print("用户名或密码错误，登录失败！")
    return None


# 增加书籍
def book_add(books):
    title = input("请输入书名：")
    # 检查书名是否已存在
    for book in books:
        if book.title == title:
            print("该书籍已存在，无需重复添加！")
            return books

    try:
        prize = int(input("请输入价格："))
        if prize <= 0:
            print("价格必须为正数，请重新输入！")
            return books

        cben = int(input("请输入成本："))
        if cben <= 0:
            print("成本必须为正数，请重新输入！")
            return books

        # 生成不重复的编号
        while True:
            number = sui_number(100, 999)
            if not any(book.number == number for book in books):
                break

        sub = input("请输入分类：")
        shuliang = int(input("请输入数量："))
        if shuliang < 0:
            print("数量不能为负数，请重新输入！")
            return books

        books.append(Book(title, prize, cben, number, sub, shuliang))
        write_books_csv(books)
        print("书籍添加成功！")
    except ValueError:
        print("输入的价格、成本或数量不是有效的整数，请重新操作。")
    return books


# 删除书籍
def book_del(books):
    try:
        # 先显示所有书籍编号和名称，方便用户选择
        print("\n当前书籍列表（编号-书名）：")
        for book in books:
            print(f"{book.number} - {book.title}")

        number = int(input("\n请输入要删除书籍的编号："))
        for i, book in enumerate(books):
            if book.number == number:
                # 二次确认
                confirm = input(f"确定要删除《{book.title}》吗？(y/n)：")
                if confirm.lower() == 'y':
                    del books[i]
                    write_books_csv(books)
                    print("书籍删除成功！")
                else:
                    print("已取消删除操作")
                return books
        print("未找到该编号的书籍！")
    except ValueError:
        print("输入的编号不是有效的整数，请重新操作。")
    return books


# 修改书籍数据
def book_gai(books):
    try:
        # 先显示所有书籍编号和名称
        print("\n当前书籍列表（编号-书名）：")
        for book in books:
            print(f"{book.number} - {book.title}")

        number = int(input("\n请输入要修改书籍的编号："))
        for book in books:
            if book.number == number:
                print("当前书籍信息：")
                book.show_detailed()

                # 提供修改选项列表
                print("修改选项：")
                print("1：书名 | 2：价格 | 3：成本 | 4：分类 | 5：数量 | 6：批量修改 | 0：退出修改")
                choice = input("请选择要修改的内容：")

                if choice == "1":
                    new_title = input("请输入新书名：")
                    book.title = new_title
                elif choice == "2":
                    new_prize = int(input("请输入新价格："))
                    if new_prize > 0:
                        book.prize = new_prize
                    else:
                        print("价格必须为正数，修改失败")
                elif choice == "3":
                    new_cben = int(input("请输入新成本："))
                    if new_cben > 0:
                        book.cben = new_cben
                    else:
                        print("成本必须为正数，修改失败")
                elif choice == "4":
                    book.sub = input("请输入新分类：")
                elif choice == "5":
                    new_shuliang = int(input("请输入新数量："))
                    if new_shuliang >= 0:
                        book.shuliang = new_shuliang
                    else:
                        print("数量不能为负数，修改失败")
                elif choice == "6":
                    # 批量修改功能
                    print("开始批量修改...")
                    book.title = input("请输入新书名：")
                    book.prize = int(input("请输入新价格："))
                    book.cben = int(input("请输入新成本："))
                    book.sub = input("请输入新分类：")
                    book.shuliang = int(input("请输入新数量："))
                elif choice == "0":
                    print("退出修改。")
                    return books
                else:
                    print("无效选项，修改失败")
                    return books

                write_books_csv(books)
                print("书籍修改成功！")
                return books
        print("未找到该编号的书籍！")
    except ValueError:
        print("输入的编号、价格、成本或数量不是有效的整数，请重新操作。")
    return books


# 查找书籍功能 - 优化版本
def book_find(books):
    while True:
        print("\n查找方式：")
        print("1：按书名查找 | 2：按分类查找 | 3：按编号查找 | 4：总览所有书籍 | 0：返回上级")
        choice = input("请选择查找方式：")

        if choice == "0":
            print("返回上级菜单")
            break

        found = False
        if choice == "1":
            keyword = input("请输入要查找的书名关键词：")
            print(f"\n查找结果（书名包含'{keyword}'）：")
            for book in books:
                if keyword in book.title:
                    book.show()
                    found = True

        elif choice == "2":
            # 先显示所有可用分类
            categories = set(book.sub for book in books)
            print(f"可用分类：{', '.join(categories)}")
            keyword = input("请输入要查找的分类：")
            print(f"\n查找结果（分类为'{keyword}'）：")
            for book in books:
                if keyword == book.sub:
                    book.show()
                    found = True

        elif choice == "3":
            try:
                number = int(input("请输入要查找的书籍编号："))
                print(f"\n查找结果（编号为'{number}'）：")
                for book in books:
                    if book.number == number:
                        book.show_detailed()  # 编号查找显示详细信息
                        found = True
                        break
            except ValueError:
                print("输入的编号不是有效的整数")
                continue

        elif choice == "4":
            print("\n总览选项：")
            print("1：按编号排序显示 | 2：按库存量排序显示 | 3：按分类分组显示 | 0：返回")
            sub_choice = input("请选择总览方式：")

            if sub_choice == "1":
                sorted_books = sorted(books, key=lambda x: x.number)
                print("\n按编号排序的所有书籍：")
            elif sub_choice == "2":
                sorted_books = sorted(books, key=lambda x: x.shuliang, reverse=True)
                print("\n按库存量从高到低排序的所有书籍：")
            elif sub_choice == "3":
                # 按分类分组
                categories = {}
                for book in books:
                    if book.sub not in categories:
                        categories[book.sub] = []
                    categories[book.sub].append(book)

                print("\n按分类分组的所有书籍：")
                for cat, cat_books in categories.items():
                    print(f"\n【分类：{cat}】共 {len(cat_books)} 本")
                    for book in cat_books:
                        book.show()
                found = True
                continue
            elif sub_choice == "0":
                continue
            else:
                print("无效的总览选项")
                continue

            # 显示排序后的书籍
            for book in sorted_books:
                book.show()
            found = True

        else:
            print("无效的查找方式")
            continue

        if not found:
            print("未找到相关书籍！")


# 排序功能
def book_sort(books):
    print("\n排序选项：")
    print("1：按价格排序（低到高） | 2：按价格排序（高到低）")
    print("3：按库存量排序（低到高） | 4：按库存量排序（高到低）")
    print("5：按编号排序（小到大） | 6：按书名排序（字母顺序）")
    choice = input("请选择排序方式：")

    if choice == "1":
        sorted_books = sorted(books, key=lambda x: x.prize)
        print("\n按价格从低到高排序：")
    elif choice == "2":
        sorted_books = sorted(books, key=lambda x: x.prize, reverse=True)
        print("\n按价格从高到低排序：")
    elif choice == "3":
        sorted_books = sorted(books, key=lambda x: x.shuliang)
        print("\n按库存量从低到高排序：")
    elif choice == "4":
        sorted_books = sorted(books, key=lambda x: x.shuliang, reverse=True)
        print("\n按库存量从高到低排序：")
    elif choice == "5":
        sorted_books = sorted(books, key=lambda x: x.number)
        print("\n按编号从小到大排序：")
    elif choice == "6":
        sorted_books = sorted(books, key=lambda x: x.title)
        print("\n按书名字母顺序排序：")
    else:
        print("无效的排序选项")
        return books

    # 显示排序结果
    for book in sorted_books:
        book.show()

    # 询问是否保存排序结果（仅改变显示顺序，不改变实际存储）
    return books


# 借走书籍
def book_borrow(books, user):
    # 先显示可借阅的书籍（库存量>0）
    available_books = [b for b in books if b.shuliang > 0]
    if not available_books:
        print("抱歉，目前没有可借阅的书籍！")
        return books

    print("\n可借阅书籍列表：")
    for book in available_books:
        print(f"编号：{book.number} | 书名：{book.title} | 剩余：{book.shuliang}")

    try:
        number = int(input("\n请输入要借走书籍的编号："))
        for book in books:
            if book.number == number:
                if book.shuliang > 0:
                    # 询问借阅数量
                    borrow_count = 1
                    if book.shuliang > 1:
                        try:
                            borrow_count = int(input(f"最多可借{book.shuliang}本，请输入借阅数量："))
                            if borrow_count < 1 or borrow_count > book.shuliang:
                                print(f"借阅数量必须在1到{book.shuliang}之间")
                                return books
                        except ValueError:
                            print("输入的数量不是有效的整数，默认借阅1本")

                    book.shuliang -= borrow_count
                    # 记录借书历史，格式为“书名-编号-数量-日期(模拟)”
                    import datetime
                    today = datetime.datetime.now().strftime("%Y-%m-%d")
                    user.borrow_history.append(f"{book.title}-{book.number}-{borrow_count}-{today}")

                    write_books_csv(books)
                    write_users_csv(read_users_csv())
                    print(f"成功借走《{book.title}》{borrow_count}本，剩余数量：{book.shuliang}")
                else:
                    print("该书籍已无库存，无法借走！")
                return books
        print("未找到该编号的书籍！")
    except ValueError:
        print("输入的编号不是有效的整数，请重新操作。")
    return books


# 归还书籍
def book_return(books, user):
    # 显示用户当前借阅的书籍
    if not user.borrow_history:
        print("您没有借阅任何书籍，无需归还！")
        return books

    print("\n您当前借阅的书籍：")
    for i, record in enumerate(user.borrow_history):
        # 解析记录：书名-编号-数量-日期
        parts = record.split('-')
        if len(parts) >= 3:
            print(f"{i + 1}. 书名：{parts[0]} | 编号：{parts[1]} | 数量：{parts[2]} | 借出日期：{parts[3]}")

    try:
        number = int(input("\n请输入要归还书籍的编号："))
        for book in books:
            if book.number == number:
                # 查找用户借阅记录
                book_key = f"{book.title}-{book.number}"
                matching_records = [r for r in user.borrow_history if book_key in r]

                if not matching_records:
                    print("您没有借阅过这本书，无法归还！")
                    return books

                # 解析可归还数量
                total_borrowed = 0
                for r in matching_records:
                    parts = r.split('-')
                    if len(parts) >= 3:
                        total_borrowed += int(parts[2])

                # 询问归还数量
                return_count = 1
                if total_borrowed > 1:
                    try:
                        return_count = int(input(f"您共借了{total_borrowed}本，请输入归还数量："))
                        if return_count < 1 or return_count > total_borrowed:
                            print(f"归还数量必须在1到{total_borrowed}之间")
                            return books
                    except ValueError:
                        print("输入的数量不是有效的整数，默认归还1本")

                book.shuliang += return_count

                # 更新借阅历史
                remaining = return_count
                for r in matching_records[:]:
                    if remaining <= 0:
                        break

                    parts = r.split('-')
                    if len(parts) >= 3:
                        rec_count = int(parts[2])
                        if rec_count <= remaining:
                            user.borrow_history.remove(r)
                            remaining -= rec_count
                        else:
                            # 部分归还
                            new_rec = f"{parts[0]}-{parts[1]}-{rec_count - remaining}-{parts[3]}"
                            idx = user.borrow_history.index(r)
                            user.borrow_history[idx] = new_rec
                            remaining = 0

                write_books_csv(books)
                write_users_csv(read_users_csv())
                print(f"成功归还《{book.title}》{return_count}本，当前数量：{book.shuliang}")
                return books
        print("未找到该编号的书籍！")
    except ValueError:
        print("输入的编号不是有效的整数，请重新操作。")
    return books


# 卖书（交易环节）
def book_sell(books, user):
    # 先显示可购买的书籍
    available_books = [b for b in books if b.shuliang > 0]
    if not available_books:
        print("抱歉，目前没有可购买的书籍！")
        return books

    print("\n可购买书籍列表：")
    for book in available_books:
        print(f"编号：{book.number} | 书名：{book.title} | 价格：{book.prize} | 库存：{book.shuliang}")

    try:
        number = int(input("\n请输入要购买书籍的编号："))
        for book in books:
            if book.number == number:
                if book.shuliang > 0:
                    # 显示书籍详细信息和价格
                    print(f"\n您选择的书籍：《{book.title}》，单价：{book.prize}元，库存：{book.shuliang}本")

                    count = int(input("请输入购买数量："))
                    if count <= 0:
                        print("购买数量必须为正数！")
                        return books

                    if count <= book.shuliang:
                        total_price = book.prize * count
                        print(f"购买{count}本《{book.title}》，总价：{total_price}元")

                        # 提供折扣信息
                        discount = 1.0
                        if count >= 5:
                            discount = 0.9
                            print(f"购买5本及以上享受9折优惠，折后总价：{total_price * discount:.2f}元")

                        confirm = input("是否确认购买？（y/n）：")
                        if confirm.lower() == "y":
                            book.shuliang -= count
                            # 记录购买历史，格式为“书名-编号-数量-总价-日期”
                            import datetime
                            today = datetime.datetime.now().strftime("%Y-%m-%d")
                            final_price = total_price * discount
                            user.purchase_history.append(
                                f"{book.title}-{book.number}-{count}-{final_price:.2f}-{today}")

                            write_books_csv(books)
                            write_users_csv(read_users_csv())
                            print(f"购买成功！实际支付：{final_price:.2f}元")
                        else:
                            print("已取消购买。")
                    else:
                        print(f"库存不足，当前库存：{book.shuliang}")
                else:
                    print("该书籍已无库存，无法购买！")
                return books
        print("未找到该编号的书籍！")
    except ValueError:
        print("输入的编号或数量不是有效的整数，请重新操作。")
    return books


# 主功能函数（管理员使用）
def main_func(books):
    while True:
        print("\n管理功能菜单：")
        print("1：增加书籍 | 2：删除书籍 | 3：修改书籍数据")
        print("4：查找书籍 | 5：排序书籍 | 6：查看用户列表")
        print("0：返回上级")
        ans = input("请输入选项：")

        if ans == "1":
            books = book_add(books)
        elif ans == "2":
            books = book_del(books)
        elif ans == "3":
            books = book_gai(books)
        elif ans == "4":
            book_find(books)
        elif ans == "5":
            books = book_sort(books)
        elif ans == "6":
            # 查看用户列表功能
            users = read_users_csv()
            print("\n系统用户列表：")
            for i, user in enumerate(users):
                role = "管理员" if user.is_admin else "普通用户"
                print(
                    f"{i + 1}. 用户名：{user.username} | 身份：{role} | 借阅记录：{len(user.borrow_history)}条 | 购买记录：{len(user.purchase_history)}条")
        elif ans == "0":
            print("返回上级菜单。")
            break
        else:
            print("无效选项，请重新输入。")
    return books


# 普通用户功能函数
def user_func(books, user):
    while True:
        print("\n用户功能菜单：")
        print("1：查找书籍 | 2：借走书籍 | 3：归还书籍")
        print("4：购买书籍 | 5：排序书籍 | 6：查看我的记录")
        print("0：返回上级")
        ans = input("请输入选项：")

        if ans == "1":
            book_find(books)
        elif ans == "2":
            books = book_borrow(books, user)
        elif ans == "3":
            books = book_return(books, user)
        elif ans == "4":
            books = book_sell(books, user)
        elif ans == "5":
            books = book_sort(books)
        elif ans == "6":
            # 查看个人记录
            print("\n--- 我的借阅记录 ---")
            if user.borrow_history:
                for i, record in enumerate(user.borrow_history):
                    parts = record.split('-')
                    if len(parts) >= 3:
                        print(f"{i + 1}. 书名：{parts[0]} | 编号：{parts[1]} | 数量：{parts[2]} | 借出日期：{parts[3]}")
            else:
                print("暂无借阅记录")

            print("\n--- 我的购买记录 ---")
            if user.purchase_history:
                total_spent = 0
                for i, record in enumerate(user.purchase_history):
                    parts = record.split('-')
                    if len(parts) >= 4:
                        print(f"{i + 1}. 书名：{parts[0]} | 数量：{parts[2]} | 金额：{parts[3]}元 | 日期：{parts[4]}")
                        total_spent += float(parts[3])
                print(f"累计消费：{total_spent:.2f}元")
            else:
                print("暂无购买记录")
        elif ans == "0":
            print("返回上级菜单。")
            break
        else:
            print("无效选项，请重新输入。")
    return books


# 启动函数
def start():
    # 读取书籍数据
    books = read_books_csv()
    # 读取用户数据
    users = read_users_csv()

    while True:
        print("\n" + "-" * 20, "欢迎使用图书馆管理系统", "-" * 20)
        print("1：用户注册 | 2：用户登录 | 0：退出系统")
        choice = input("请输入操作选项：")

        if choice == "1":
            users = user_register(users)
        elif choice == "2":
            user = user_login(users)
            if user:
                if user.is_admin:
                    print("管理员登录成功，进入管理界面。")
                    books = main_func(books)
                else:
                    print("普通用户登录成功，进入用户界面。")
                    books = user_func(books, user)
        elif choice == "0":
            print("退出系统，谢谢使用！")
            break
        else:
            print("无效选项，请重新输入。")


# 启动程序
start()
print("-" * 20, "程序结束", "-" * 20)
